package com.disruptor.demo.config;

import com.disruptor.demo.event.SeckillOrderEvent;
import com.disruptor.demo.factory.SeckillOrderEventFactory;
import com.disruptor.demo.handler.OrderProcessHandler;
import com.disruptor.demo.handler.ResultNotifyHandler;
import com.disruptor.demo.handler.SeckillOrderExceptionHandler;
import com.disruptor.demo.handler.StockCheckHandler;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import com.lmax.disruptor.util.DaemonThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * Disruptor核心配置类
 * 功能：1. 初始化Disruptor框架核心实例 2. 定义消费者处理器的依赖关系 3. 配置Disruptor关键参数
 * 作用：作为Disruptor与Spring的整合入口，确保所有组件按依赖顺序启动和运行
 */
@Slf4j
@Configuration
public class DisruptorConfig {
    // ========================== 注入业务处理器（Spring管理的Bean） ==========================
    /**
     * 库存校验处理器：负责秒杀库存的校验与扣减，是消费链的第一步
     */
    @Resource
    private StockCheckHandler stockCheckHandler;
    /**
     * 订单处理处理器：负责订单数据的业务处理（如模拟入库），依赖库存校验完成
     */
    @Resource
    private OrderProcessHandler orderProcessHandler;
    /**
     * 结果通知处理器：负责向用户推送下单结果，依赖订单处理完成
     */
    @Resource
    private ResultNotifyHandler resultNotifyHandler;
    /**
     * 全局异常处理器：捕获所有消费者的未处理异常，避免Disruptor因异常终止
     */
    @Resource
    private SeckillOrderExceptionHandler exceptionHandler;

    // ========================== 注入配置文件参数（可动态调整） ==========================
    /**
     * RingBuffer大小：环形缓冲区容量，必须为2的幂次方（如16384=2^14），用于预分配事件对象
     */
    @Value("${disruptor.ring-buffer-size}")
    private int ringBufferSize;
    /**
     * 生产者类型：MULTI（多生产者，支持并发发布事件）/SINGLE（单生产者，性能略高）
     */
    @Value("${disruptor.producer-type}")
    private String producerType;
    /**
     * 等待策略：定义消费者等待事件的方式，影响延迟与CPU占用
     */
    @Value("${disruptor.wait-strategy}")
    private String waitStrategy;
    /**
     * 消费者线程名前缀：用于日志排查，区分不同处理器的线程
     */
    @Value("${disruptor.handler-thread-prefix}")
    private String handlerThreadPrefix;

    // ========================== 核心Bean：初始化Disruptor实例 ==========================

    /**
     * 初始化Disruptor核心实例
     *
     * @return Disruptor<SeckillOrderEvent> 配置完成的Disruptor实例
     * @destroyMethod "shutdown"：Spring容器关闭时，自动调用Disruptor的shutdown()方法，优雅关闭（避免事件丢失）
     */
    @Bean(destroyMethod = "shutdown")
    public Disruptor<SeckillOrderEvent> seckillDisruptor() {
        // 1. 创建事件工厂：Disruptor启动时，通过工厂预创建所有RingBuffer容量的事件对象，减少运行时GC
        SeckillOrderEventFactory eventFactory = new SeckillOrderEventFactory();

        // 2. 选择等待策略：根据业务场景选择，此处默认YieldingWaitStrategy（秒杀场景最优）
        // - YieldingWaitStrategy：自旋+Thread.yield()，平衡低延迟（微秒级）与CPU占用，适合高并发秒杀
        // - BusySpinWaitStrategy：纯自旋，延迟最低但CPU占用极高，适合金融高频交易
        // - BlockingWaitStrategy：基于锁+条件变量，CPU占用低但延迟高（毫秒级），适合后台非实时任务
        com.lmax.disruptor.WaitStrategy strategy = new com.lmax.disruptor.YieldingWaitStrategy();

        // 3. 确定生产者类型：根据是否多线程发布事件选择
        // - ProducerType.MULTI：支持多线程并发发布事件（秒杀场景必须，多用户同时下单）
        // - ProducerType.SINGLE：仅支持单线程发布，避免多线程CAS竞争，性能略高
        ProducerType producerTypeEnum = "MULTI".equals(producerType)
                ? ProducerType.MULTI
                : ProducerType.SINGLE;

        // 4. 初始化Disruptor实例：传入核心配置参数
        Disruptor<SeckillOrderEvent> disruptor = new Disruptor<>(
                eventFactory,          // 事件工厂：预创建事件
                ringBufferSize,        // RingBuffer大小：预分配的事件数量
                DaemonThreadFactory.INSTANCE, // 守护线程工厂：线程为守护线程，Spring容器关闭时自动退出（避免阻塞服务停止）
                producerTypeEnum,      // 生产者类型：多生产者/单生产者
                strategy               // 等待策略：消费者等待事件的方式
        );

        // 5. 配置全局异常处理器：为所有消费者设置统一异常处理，避免单个事件处理失败导致整个Disruptor终止
        disruptor.setDefaultExceptionHandler(exceptionHandler);

        // 6. 构建消费者链：定义处理器的串行依赖关系（核心逻辑）
        // - handleEventsWith(stockCheckHandler)：第一个处理器（库存校验）
        // - .then(orderProcessHandler)：第二个处理器，必须等待第一个处理器完成后才执行（订单处理）
        // - .then(resultNotifyHandler)：第三个处理器，必须等待第二个处理器完成后才执行（结果通知）
        // 作用：确保业务流程顺序（库存校验→订单处理→结果通知），避免数据不一致
        disruptor.handleEventsWith(stockCheckHandler)
                .then(orderProcessHandler)
                .then(resultNotifyHandler);

        // 7. 启动Disruptor：启动消费者线程池，开始监听RingBuffer的事件（启动后不可修改配置）
        disruptor.start();

        // 8. 打印初始化日志：记录关键配置参数，方便后续问题排查（如RingBuffer大小是否符合预期）
        log.info("Disruptor初始化完成：ringBufferSize={}, producerType={}, waitStrategy={}",
                ringBufferSize,
                producerTypeEnum.name(),
                strategy.getClass().getSimpleName());

        return disruptor;
    }

    // ========================== 辅助Bean：暴露RingBuffer供生产者使用 ==========================

    /**
     * 暴露Disruptor内部的RingBuffer实例
     *
     * @param seckillDisruptor 已初始化的Disruptor实例
     * @return RingBuffer<SeckillOrderEvent> Disruptor的事件缓冲区
     * 作用：生产者（SeckillOrderProducer）需要通过RingBuffer发布事件，因此将其注入Spring容器
     */
    @Bean
    public RingBuffer<SeckillOrderEvent> seckillRingBuffer(Disruptor<SeckillOrderEvent> seckillDisruptor) {
        // 从Disruptor实例中获取RingBuffer（Disruptor启动后，RingBuffer已初始化完成）
        return seckillDisruptor.getRingBuffer();
    }
}
